
#include <stdio.h>
#include <BPainter>
#include <BHBoxLayout>
#include <BVBoxLayout>
#include <BStyle>
#include <BSonDocument>
#include <BOpenGL>
#include <BImage>

#include "ClientWidget.h"

ClientWidget::ClientWidget()
{
	_loginWidget = new LoginDialog(this);

	BHBoxLayout* topLayout = new BHBoxLayout();
	{
		_connectButton = new BButton("Connect");
		_loginButton = new BButton("Login");
		_quitButton = new BButton("Quit");
		topLayout->addSpring();
		topLayout->addWidget(_connectButton);
		topLayout->addWidget(_loginButton);
		topLayout->addWidget(_quitButton);
		this->setLayout(topLayout, Part_Top);
	}

	_dialogList = new DialogListWidget();

	BHBoxLayout* inputLayout = new BHBoxLayout();
	{
		_inputEdit = new BLineEdit();
		_sendButton = new BButton("send");
		inputLayout->addWidget(_inputEdit);
		inputLayout->addWidget(_sendButton, 0);
	}

	BVBoxLayout* vlayout = new BVBoxLayout(this);
	vlayout->addWidget(_dialogList);
	vlayout->addLayout(inputLayout, 0);

	_socket = new BTcpSocket();
	_loginWidget->setSocket(_socket);

	connect(_connectButton, Signal_Clicked, &ClientWidget::slotConnectButtonClicked);
	connect(_connectButton, Signal_Frame, &ClientWidget::slotConnectButtonFrame);
	connect(_loginButton, Signal_Clicked, &ClientWidget::slotLoginButtonClicked);
	connect(_quitButton, Signal_Clicked, &ClientWidget::slotQuitButtonClicked);
	connect(_inputEdit, Signal_KeyPress, &ClientWidget::slotInputEditKeyDown);
	connect(_sendButton, Signal_Clicked, &ClientWidget::slotSendButtonClicked);

	connect(_socket, Signal_Error, &ClientWidget::slotSocketError);
	connect(_socket, Signal_Disconnected, &ClientWidget::slotSocketDisconnected);
	connect(_socket, Signal_ReadyRead, &ClientWidget::slotSocketReadyRead);
}
ClientWidget::~ClientWidget()
{

}

void ClientWidget::setServerAddress(const BString& address)
{
	_serverAddress = address;
}
bool ClientWidget::sendMessage()
{
	const BString& text = _inputEdit->text();
	if (text.empty())
		return false;
	BString message("message{");
	message << text << "}";
	_socket->send(message);
	DialogListItem* item = new DialogListItem();
	item->setText(text);
	item->setIcon(this->asset());
	item->setAlign(Align_Left);
	_dialogList->addItem(item);
	_inputEdit->setText(BString());
	return true;
}

void ClientWidget::slotConnectButtonClicked()
{
	if(_serverAddress.size() && _socket->state() == BSocket::State_Closed)
	{
		if (_socket->connectServer(_serverAddress))
		{
			BString infoText("connect to ");
			infoText << _serverAddress << " successful.";
			DialogListItem* item = new DialogListItem();
			item->setText(infoText);
			item->setAlign(Align_Center);
			_dialogList->addItem(item);
		}
	}
}
void ClientWidget::slotConnectButtonFrame(BObject* object)
{
	if (!object->enabled())
	{
		BWidget* widget = dynamic_cast<BWidget*>(object);
		const BStyle* style = this->realStyle();
		if (widget && style)
		{
			static float angle = 0.0f;
			BImage* image = style->image("refresh");
			if (image)
			{
				BPainter painter(widget);
				BRect crect = widget->centerRect();
				BRect rect = crect.size().wrap(image->size());
				painter.translate(rect.width() / 2.0f, rect.height() / 2.0f);
				painter.rotate(angle, 0.0f, 0.0f, 1.0f);
				painter.translate(-rect.width() / 2.0f, -rect.height() / 2.0f);
				painter.drawImage(rect, image);
			}
			angle += 33;
			if (angle >= 360.0f)
				angle = 0.0f;
		}
	}
}
void ClientWidget::slotLoginButtonClicked()
{
	_loginWidget->popup();
}
void ClientWidget::slotQuitButtonClicked()
{

}
void ClientWidget::slotInputEditKeyDown(BObject* object, const BValue& value)
{
	Key key = value;
	if (key == Key_Enter)
	{
		sendMessage();
	}
}
void ClientWidget::slotSendButtonClicked()
{
	sendMessage();
}

void ClientWidget::slotSocketError()
{
	puts(_socket->errorStr());
}
void ClientWidget::slotSocketDisconnected(BObject* object, const BValue& value)
{
	BString infoText("disconnected of ");
	infoText << _serverAddress;
	DialogListItem* item = new DialogListItem();
	item->setText(infoText);
	item->setAlign(Align_Center);
	_dialogList->addItem(item);
}
void ClientWidget::slotSocketReadyRead(BObject* object, const BValue& value)
{
	_buffer.seek(_buffer.size());
	int size = _socket->recv(_buffer);
	_buffer.seek(0);
	BSonDocument doc;
	if (BSonNode* node = doc.read(_buffer))
	{
		if (node->name() == "message")
		{
			const BString& text = node->text();
			DialogListItem* item = new DialogListItem();
			item->setName(_socket->name());
			item->setText(text);
			item->setIcon(_serverIcon);
			item->setAlign(Align_Right);
			item->setForm(Form_TextIcon);
			_dialogList->addItem(item);
		}
		_buffer.bytes().remove(0, _buffer.offset());
	}
}
void ClientWidget::slotSocketBytesSent(BObject* object, const BValue& value)
{

}

void ClientWidget::updateEvent(const BEvent& event)
{
	if (_socket->state() == BSocket::State_Connected)
	{
		_inputEdit->setEnabled(true);
		_loginButton->setEnabled(true);
		_quitButton->setEnabled(true);
		_sendButton->setEnabled(true);
	}
	else
	{
		_inputEdit->setEnabled(false);
		_loginButton->setEnabled(false);
		_quitButton->setEnabled(false);
		_sendButton->setEnabled(false);
	}
	if (_socket->state() == BSocket::State_Connecting)
	{
		_connectButton->setEnabled(false);
		_connectButton->fresh();
	}
	else
	{
		_connectButton->setEnabled(true);
		_connectButton->fresh();
	}
}
void ClientWidget::styleEvent(const BEvent& event)
{
	const BStyle* style = event.value();
	this->setAsset(style->icon("client"));
	_serverIcon = style->icon("server");
}
void ClientWidget::paintEvent(const BEvent& event)
{
	BWidget::paintEvent(event);

	BLayout* layout = this->layout(Part_Top);
	BRect textRect = layout->rect();

	BPainter painter(this);
	painter.setColor(Color_Text);
	painter.drawText(textRect, _serverAddress);
}

